package org.example.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Verification;

import java.util.*;

/**
 * JWTUtil类用于处理JWT（JSON Web Token）的创建、验证和信息提取
 */
public class JWTUtil {
    // 定义用于签名和验证的密钥
    private static String key = "a-string-secret-at-least-256-bits-long";

    /**
     * 创建一个JWT token
     *
     * @param map 包含要存储在token中的用户信息的映射
     * @return 返回生成的JWT token字符串
     */
    public static String createToken(Map<String, Object> map) {
        // 创建头部信息，指定算法和类型
        Map<String, Object> head = new HashMap<>();
        head.put("alg", "HS256");
        head.put("typ", "JWT");

        // 获取当前日期作为发布日期
        Date date = new Date();
        // 获取当前时间，并在基础上添加7200秒作为过期时间
        Calendar instance = Calendar.getInstance();
        instance.set(Calendar.SECOND, 7200);
        Date time = instance.getTime();

        // 构建JWT token
        String token = JWT.create().withHeader(head) // 设置头部信息
                .withIssuedAt(date) // 设置发布日期
                .withExpiresAt(time) // 设置过期时间
                .withClaim("userinfo", map) // 添加用户信息
                .sign(Algorithm.HMAC256(key)); // 使用密钥签名

        return token;
    }

    /**
     * 验证JWT token的有效性
     *
     * @param token 要验证的JWT token字符串
     * @return 如果token有效返回true，否则返回false
     */
    public static boolean verify(String token) {
        // 使用密钥创建验证器
        Verification require = JWT.require(Algorithm.HMAC256(key));
        try {
            // 尝试验证token，如果成功则token有效
            require.build().verify(token);
            return true;
        } catch (Exception e) {
            // 如果验证失败，输出错误信息并返回false
            System.out.println("token错误");
            return false;
        }
    }

    /**
     * 解析 Base64Url 编码的字符串
     *
     * @param base64Url Base64Url 编码的字符串
     * @return 返回解码后的字符串
     */
    public static String decodeBase64Url(String base64Url) {
        // 补全 Base64Url 的 padding（如果需要）
        int padding = (4 - (base64Url.length() % 4)) % 4;
        StringBuilder base64 = new StringBuilder(base64Url);
        for (int i = 0; i < padding; i++) {
            base64.append("=");
        }

        // 替换 Base64Url 中的特殊字符 '+' -> '-', '/' -> '_'
        String base64Padded = base64.toString()
                .replace('-', '+')
                .replace('_', '/');

        // 使用 Java 8+ 的 Base64 解码器
        return new String(Base64.getDecoder().decode(base64Padded));
    }

    /**
     * 主程序入口
     * 本程序主要用于演示如何创建和验证JWT（Json Web Token）
     *
     * @param args 命令行参数，本例中未使用
     */
    public static void main(String[] args) {
        // 创建一个HashMap实例，用于存储用户信息
        Map userMap = new HashMap();
        // 添加用户名到用户信息Map中
        userMap.put("username", "admin");
        // 调用工具类JWTUtil的createToken方法，创建JWT
        String token = JWTUtil.createToken(userMap);
        // 输出生成的Token
        System.out.println("Token:" + token);
        // 调用JWTUtil的verify方法验证Token的有效性
        boolean verify = JWTUtil.verify(token);
        // 输出验证结果
        System.out.println("验证结果：" + verify);
        // 如果Token验证通过，则进一步处理Token
        if (verify) {
            // 将Token按"."分割成三个部分：header、payload和signature
            String[] splits = token.split("\\.");
            // 解码Token的header部分，并输出
            String header = JWTUtil.decodeBase64Url(splits[0]);
            System.out.println("header:" + header);
            // 解码Token的payload部分，并输出，这部分通常包含用户信息和Token的过期时间等
            String payload = JWTUtil.decodeBase64Url(splits[1]);
            System.out.println("payload:" + payload);
        }
    }


}

